#ifndef FONCTIONS_H
#define FONCTIONS_H


typedef struct symbole 
{
    char* name;                 //nom de la variable
    int index;                  //index de l'élément dans la liste chainée
    int type;                   //type (BOOL,INT,STRING,...) défini dans fonctions.h
    int offset;                 //offset dans la pile MIPS
    struct fonction* fonction;
    struct symbole* next;       //prochain element de la lsite
} s_symbole;

typedef struct table
{
    s_symbole* first;
    s_symbole* last;
} s_table;

s_table * tab_symb;



#define TYPE_BOOL 0
#define TYPE_INT 1
#define TYPE_UNIT 2
#define TYPE_FONCTION 3

typedef struct cell 
{
    char* string;
    int val;
    int index;
    struct cell* next;
} s_cell;

typedef struct list_cell
{
    s_cell* first;
    s_cell* last;
} s_list_cell;

s_list_cell* strings;


#define WRITE_STRING 1
#define WRITELN_STRING 2
#define WRITE_CST_INT 3
#define WRITELN_CST_INT 4
#define WRITE_INT 5
#define WRITELN_INT 6
#define AFFECT 7
#define OP_ADD 8
#define OP_SUB 9
#define OP_MUL 10
#define OP_DIV 11
#define COMP_EGAL 20
#define COMP_INF 21
#define COMP_SUP 22
#define COMP_INF_EGAL 23
#define COMP_SUP_EGAL 24
#define COMP_NOT_EGAL 25
#define AFFECT_REGISTRE 70
#define STOCK_REGISTRE 71
#define GOTO 80
#define IFGOTO 81
#define CST 99
#define ALLOC 100
#define FREE 110
#define APPELFONCTION 120
#define RETURN 121
#define PLACER_ARG 122
#define INCONNU -1
#define READ 1234

typedef struct quad
{
    int index;
    int type;
    int cst;
    int arg1;
    int arg2;
    int res;
} s_quad;

typedef struct quadnext
{
	s_quad* q;
	struct quadnext* next;
} s_quadnext;

typedef struct list_quad
{
    s_quadnext* first;
    s_quadnext* last;
} s_list_quad;

s_list_quad* quads;

typedef struct fonction
{
    char * name;
    int index;
    s_table * tab_symb_locale;
    s_list_quad * quads;
    int type_retour;
} s_fonction;

s_fonction* fct_en_cours;
int indexFonction;

typedef struct expr
{
    s_symbole* symbole;
    s_list_quad* true;
    s_list_quad* false;
} s_expr;

typedef struct instr
{
    s_list_quad* next;
} s_instr;

struct n
{
    s_list_quad* next;
    int quad;
};

/* Global */
void ecrireCode(char* inputFileName);
void ecrirequad(FILE* file, s_quad* q, int idx_fonction);
/* Segment DATA */
int ajouterString(char* chaine);
s_list_cell* rajouterList(s_list_cell* list,char *id); 
/* Fonction qui détruit la liste passé en paramètre */
void detruireList(s_list_cell* l);


/* Segment TEXT */
void genString(int type, int index);
s_quad* gen(int type, s_symbole* arg1, s_symbole* arg2, s_symbole* res);
void genCST(int type, int cst, s_symbole* res);
void genFREE(int type, int cst);
void genGoto(int type, int label);
s_quad* genIfGoto(int type, s_symbole* arg1, int label);
void genAffectResgistre(int type,s_symbole* arg1, int registre);
void genAppelFonction(int type, s_fonction* fonct);
void genStockResgistre(int type,s_symbole* arg1, int registre);
/* Ajouter un quad à la fin de la liste de quad */
s_list_quad* ajouterALaListeDeQuad(s_list_quad* listquads,s_quad* q, int aNumeroter);



/* Transforme le nom du ficher d'entrée en nom de fichier pour la sortie */
char* outFile(char* inputFileName);


char* intToString(int num);


void freeAlltmp();
void supprimerSymbole(s_symbole * s);
void ecrireTableSymbole2();// TODO : juste pour les tests -- à supprimer à la fin

/* Ajoute la liste de nom de variable dans la table des symboles */
void ajouterListeSymbole(s_list_cell* list_id, int type, int genererAllocation);
s_symbole* newtemp();
s_symbole* place(char* name, int chercherDansGlobal);


void complete(s_list_quad* list, int label);
s_list_quad* concat(s_list_quad* list1, s_list_quad* list2);

int verifType(int type, s_expr expr1, s_expr expr2);

s_fonction* newFct(char* nom);
void ajouterALaListeDeQuadActuelle(s_quad* q);
void supprimerTable_locale(s_fonction* fct, int changerOffest);
void deplacerOffset(s_table* tab, int depl);
#endif
